package com.naiterui.ehp.bs.im.service.message.handler;

import java.io.File;
import java.util.Optional;

import com.naiterui.ehp.bp.domain.PatientInquirer;
import com.naiterui.ehp.bs.im.repository.PatientInquirerRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.naiterui.ehp.bp.constants.ImConstants;
import com.naiterui.ehp.bp.support.security.HeaderConstant;
import com.naiterui.ehp.bs.im.config.MediaFileConfig;
import com.naiterui.ehp.bs.im.config.MessageConfig;
import com.naiterui.ehp.bs.im.exception.NaiteruiIMException;
import com.naiterui.ehp.bs.im.feign.EmrFeginClient;
import com.naiterui.ehp.bs.im.network.mqtt.handler.ClientStatusHandler;
import com.naiterui.ehp.bs.im.network.protocl.CustomizedMessage;
import com.naiterui.ehp.bs.im.network.protocl.Media;
import com.naiterui.ehp.bs.im.network.protocl.Message;
import com.naiterui.ehp.bs.im.network.protocl.Session;
import com.naiterui.ehp.bs.im.network.transfer.PatientTransfer;
import com.naiterui.ehp.bs.im.remote.IRemoter;
import com.naiterui.ehp.bs.im.repository.mongo.MessageDao;
import com.naiterui.ehp.bs.im.service.message.push.PushHandler;
import com.naiterui.ehp.bs.im.utils.AsynUtils;
import com.naiterui.ehp.bs.im.utils.Constants;
import com.naiterui.ehp.bs.im.utils.NameUtils;

import ws.schild.jave.MultimediaInfo;
import ws.schild.jave.MultimediaObject;

/**
 * 患者端消息处理
 */
@Service
public class PatientMessageHandler extends AbstractMessageHandler {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(PatientMessageHandler.class);

    /**
     * 消息数据持久化对象
     */
    private final MessageDao messageDao;

    /**
     * 客户端监听器
     */
    private final ClientStatusHandler clientStatusHandler;

    /**
     * 远程调用方法封装
     */
    private final IRemoter remoter;

    /**
     * push推送处理
     */
    private final PushHandler pushHandler;

    /**
     * 客户端在线状态处理类：<code>clientHandler</code>
     */
    private final ClientStatusHandler clientHandler;

    /**
     * 向微信发送消息的传输对象
     */
    // @Qualifier(value = "patientTransfer")
    private final PatientTransfer messageTransfer;

    private final MediaFileConfig mediaConfig;

    /**
     * 消息相关的配置
     */
    private final MessageConfig messageConfig;

    private PatientInquirerRepository patientInquirerRepository;

    @Autowired
    private final EmrFeginClient emrFeginClient;

    @Value("${ehp.domain.img}")
    private String imgDomain;

    public PatientMessageHandler(MessageDao messageDao, ClientStatusHandler clientStatusHandler, IRemoter remoter, PushHandler pushHandler,
                                 ClientStatusHandler clientHandler, PatientTransfer messageTransfer, MediaFileConfig mediaConfig,
                                 MessageConfig messageConfig, EmrFeginClient emrFeginClient, PatientInquirerRepository patientInquirerRepository) {
        this.messageDao = messageDao;
        this.clientStatusHandler = clientStatusHandler;
        this.remoter = remoter;
        this.pushHandler = pushHandler;
        this.clientHandler = clientHandler;
        this.messageTransfer = messageTransfer;
        this.mediaConfig = mediaConfig;
        this.messageConfig = messageConfig;
        this.emrFeginClient = emrFeginClient;
        this.patientInquirerRepository = patientInquirerRepository;
    }

    /**
     * 消息处理
     */
    @Override
    public Message<?> handleMessage(Message<?> message) throws NaiteruiIMException {

        // 准备消息发送
        message = this.preparedMessage(message);
        // 保存消息之前,清空session信息
        Session session = message.getSession();
        //message.setSession(null);

        /*
         * 是否持久化消息
         */
        boolean persist = message.getExd() == null || message.getExd().getPersistible() == null || message.getExd().getPersistible();
        if (persist) {
            // 持久化消息
            this.persistentMessage(message);
        }

        // 重新保存session信息
        message.setSession(session);

        // 发送消息
        this.sendMessage(message);

        // 消息发送后执行一些其他逻辑操作
        this.afterSendMessage(message);

        return message;
    }

    /**
     * 消息发送前的数据准备工作
     */
    @Override
    public Message<?> preparedMessage(Message<?> message) throws NaiteruiIMException {
        super.preparedMessage(message);
        // 处理消息
        int type = message.getType();
        if (type == Constants.MESSAGE_TYPE_MEDIA_AUDIO || type == Constants.MESSAGE_TYPE_MEDIA_IMG
                || type == Constants.MESSAGE_TYPE_MEDIA_VIDEO) {

            // 转换为多媒体消息内容对象
            Media media = (Media) message.getContent();
            // 截取掉域名
            media.setPath(media.getPath().replaceAll(mediaConfig.getServerDomain(), ""));
            if (type == Constants.MESSAGE_TYPE_MEDIA_AUDIO && null != message.getLastPlatform()
                    && HeaderConstant.HEADER_ORIGIN_PATIENT_WX == message.getLastPlatform()) {
                String sourcePath = media.getPath();

                sourcePath = sourcePath.replace(this.mediaConfig.getRadioRewrite(), this.mediaConfig.getRadioRoot());
                String newPath = sourcePath.replace(".amr", ".mp3");
                AsynUtils.amrToMp3(sourcePath, newPath);
                media.setPath(media.getPath().replace(".amr", ".mp3"));

                Long duration;
                try {
                    MultimediaObject multimediaObject = new MultimediaObject(new File(sourcePath));
                    duration = Optional.ofNullable(multimediaObject.getInfo()).map(MultimediaInfo::getDuration).map(o -> o / 1000).orElse(10L);
                    media.setTimeLength(duration.intValue());
                } catch (Exception e) {
                    LOGGER.error("获取音频时长失败", e);
                }
            }
        }

        return message;
    }

    /**
     * 持久化从患者端发送给医生端的消息内容
     */
    @Override
    public void persistentMessage(Message<?> message) throws NaiteruiIMException {
        super.persistentMessage(message);
        this.messageDao.saveMessage(message);
    }

    /**
     * 发送消息至医生端
     */
    @Override
    public void sendMessage(Message<?> message) throws NaiteruiIMException {

        // 获取消息接收者的当前在线状态
        boolean isOnline = this.clientHandler.isOnline(NameUtils.drMsgTopic(message.getTo().getId()));
        LOGGER.info("向医生端发送消息前的状态检查，isOnline:{}", isOnline);
        // 如果不在线则保存离线消息并发送push消息
        if (!isOnline) {
            // 保存离线消息
            this.persistentOffineMessage(message);
            // session不等于空，消息类型就诊人未完善提醒和就诊人已完善消息或者等于患者填写表单不推送push
            if (message.getSession() != null && message.getType() != ImConstants.MESSAGE_TYPE_FIRST_BIND_UNNAMED
                && message.getType() != ImConstants.MESSAGE_TYPE_INQUIRER_INFO_PERFECT) {
                // 推送离线消息push通知, 推送离线消息通知，要排除用户已经登出的情况
                if (this.clientStatusHandler.canPush(NameUtils.drMsgTopic(message.getTo().getId()))) {
                    try {
                        this.pushHandler.pushOfflineMsgNotice(Constants.PUSH_USER_TYPE_DOCTOR, message.getTo().getId(), message);
                    } catch (Exception e) {
                        LOGGER.error("push offline message notice failure, exception is {}", e.getMessage(), e);
                    }
                }
            }
        }

        // 发送消息 该处用于处理将消息发送至微信端&APP端口
        this.messageTransfer.sendMessage(message, isOnline);
    }

    /**
     * 消息发送之后的一些附加操作
     */
    @Override
    public void afterSendMessage(Message<?> message) throws NaiteruiIMException {

        /** 患者APP端发送消息 */
//        boolean usePtApp = RedisUtil.keyOps().existsKey(CommonConstant.PT_APP_LOGIN_IN + message.getFrom().getId());
        // 若患者已使用APP，并且消息来源为患者微信端，则同步患者APP(处理离线、在线状态)
        if (null != message.getLastPlatform() && HeaderConstant.HEADER_ORIGIN_PATIENT_WX == message.getLastPlatform()) {
//        if (null != message.getLastPlatform() && HeaderConstant.HEADER_ORIGIN_PATIENT_WX == message.getLastPlatform() && usePtApp) {
            // 微信音、视、图片域名处理
            int type = message.getType();
            if (type == Constants.MESSAGE_TYPE_MEDIA_AUDIO || type == Constants.MESSAGE_TYPE_MEDIA_IMG || type == Constants.MESSAGE_TYPE_MEDIA_VIDEO) {

                // 转换为多媒体消息内容对象
                Media media = (Media) message.getContent();
                // 截取掉域名
                media.setPath(media.getPath().replaceAll(mediaConfig.getServerDomain(), ""));

            }

            // 当前患者APP是否在线
            /*PatientInquirer patientInquirer = patientInquirerRepository.findByInquirerId(message.getFrom().getId());
            Long userId = patientInquirer != null ? patientInquirer.getPatientId() : message.getFrom().getId();
            boolean isOnline = this.clientHandler.isOnline(NameUtils.ptMsgTopic(userId));*/
            boolean isOnline = this.clientHandler.isOnline(NameUtils.ptMsgTopic(message.getFrom().getId()));

            // 如果不在线则保存多平台同步离线消息
            if (!isOnline) {
                // 保存患者端微信自发送离线消息
                this.persistentSyncOffineMessage(message);
            } else {
                this.messageTransfer.sendSyncOfflineMessage(message);
            }
        }
        /*
         * 如果患者发送的是病历消息，则在发送给医生后 发给患者一个回执消息
         */
        if (message.getType() == Constants.MESSAGE_TYPE_PATEINTS_MEDICAL_RECORD) {
            CustomizedMessage customizedMessage = (CustomizedMessage) message.getContent();
            Integer specificMessageKey = customizedMessage.getSpecificMessageType();
            if (specificMessageKey != null && specificMessageKey.equals(CustomizedMessage.SPEC_MESS_TYPE_PATIENTS_MEDICAL_RECORD)) {
                String wxMessageContent = String.format(
                        (message.getSession() != null && message.getSession().getConsultPayType() != null
                                && message.getSession().getConsultPayType().equals(Constants.CONSULT_PAY_TYPE_CHARGE))
                                ? this.messageConfig.getPaidMedicalRecordReceipt()
                                : this.messageConfig.getFreeMedicalRecordReceipt(),
                        message.getTo().getName());
                this.remoter.sendMsgToWx(null, null, Constants.MEDICAL_RECORD_MESSAGE_RECEIPT, message.getTo().getId(), message.getFrom().getId(),
                        wxMessageContent, null, true);
            }
        }
        // 病例发送推送信息
        if(message.getType() == Constants.MESSAGE_TYPE_PATEINTS_MEDICAL_SEND){
            this.messageTransfer.sendSyncOfflineMessage(message);
        }

        /*if (message.getType() == Constants.MESSAGE_TYPE_REMIND_PATIENTS_FILL_MEDICAL_RECORD) {
            CustomizedMessage customizedMessage = (CustomizedMessage) message.getContent();
            Integer specificMessageKey = customizedMessage.getSpecificMessageType();
            // 患者给医生发起咨询发送病情信息后处理逻辑，给医生以消息形式发送病情中的图片
            //Extend extend = message.getExd();
            Long patientId = message.getFrom().getId();
            LOGGER.info("患者发起咨询给医生发送病情消息, From {}, patientId {}", message.getFrom(), patientId);
            //String diseaseId = extend.getDiseaseId();
            try{
                PatientDiseaseBO patientDisease = emrFeginClient.getDisease(patientId);
                List<String> offlineDiagnosisImgs = patientDisease.getOfflineDiagnosisImgs();
                LOGGER.info("获取到的图片信息条数 {}", offlineDiagnosisImgs.size());
                if (CollectionUtil.isNotEmpty(offlineDiagnosisImgs)) {
                    for (String imgUrl : offlineDiagnosisImgs) {
                        // 发送图片消息
                        Message<Media> sendMessage = new Message<>();
                        BeanUtil.copyProperties(message, sendMessage);
                        sendMessage.setType(Constants.MESSAGE_TYPE_MEDIA_IMG);
                        sendMessage.setRelation(0);
                        Media media = new Media();
                        media.setPath(imgUrl);
                        sendMessage.setContent(media);
                        LOGGER.info("患者发起问诊给医生推送病情图片消息，当前图片链接地址 {}", sendMessage.getContent());
                        this.sendMessage(sendMessage);
                    }
                }
            } catch (Exception e) {
                LOGGER.error("患者发起咨询给医生发送病情图片消息异常 {}", e);
            }
        }*/
    }

    /**
     * PatientMessageHandler.persistentPtOffineMessage()
     */
    private void persistentSyncOffineMessage(Message<?> message) {
        // 保存离线消息
        this.messageDao.saveSyncOfflineMessage(message);
    }

    /**
     * 保存离线消息
     */
    private void persistentOffineMessage(Message<?> message) {
        // 保存离线消息
        this.messageDao.saveOfflineMessage(message);
    }

    @Override
    public void preValidate(Message<?> messageBean) {
    }

}
